package contegor.scire.core;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/**
 * Unmodifiable {@link List} that holds only one element but behaves as it have infinite size.
 *
 * @version $Revision$
 * @author  Héctor Cirbián Pousa ($Author$)
 */
@Version("$Id$")
public class InfiniteSingletonList<E> implements List<E> {

  private E   element;
  private int size;

  public InfiniteSingletonList(E element, int size) {
    this.element = element;
    this.size    = size;
  }

  @Override
  public boolean add(E arg0) {
    throw new UnsupportedOperationException();
  }

  @Override
  public void add(int arg0, E arg1) {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean addAll(Collection<? extends E> arg0) {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean addAll(int arg0, Collection<? extends E> arg1) {
    throw new UnsupportedOperationException();
  }

  @Override
  public void clear() {
    throw new UnsupportedOperationException();    
  }

  @Override
  public boolean contains(Object arg) {
    return element.equals(arg);
  }

  @Override
  public boolean containsAll(Collection<?> args) {
    for (Object arg: args)
      if (!element.equals(arg))
        return false;
    return true;
  }

  @Override
  public E get(int i) {
    return element;
  }

  @Override
  public int indexOf(Object arg) {
    if (element.equals(arg))
      return 0;
    return -1;
  }

  @Override
  public boolean isEmpty() {
    return false;
  }

  @Override
  public Iterator<E> iterator() {
    return new Iterator<E>() {
      @Override
      public boolean hasNext() {
        return true;
      }

      @Override
      public E next() {
        return element;
      }

      @Override
      public void remove() {
        throw new UnsupportedOperationException();            
      }
    };
  }

  @Override
  public int lastIndexOf(Object arg) {
    if (element.equals(arg))
      return 0;
    return -1;
  }

  @Override
  public ListIterator<E> listIterator() {
    throw new UnsupportedOperationException();    
  }

  @Override
  public ListIterator<E> listIterator(int arg0) {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean remove(Object arg0) {
    throw new UnsupportedOperationException();
  }

  @Override
  public E remove(int arg0) {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean removeAll(Collection<?> arg0) {
    throw new UnsupportedOperationException();
  }

  @Override
  public boolean retainAll(Collection<?> arg0) {
    throw new UnsupportedOperationException();
  }

  @Override
  public E set(int i, E arg) {
    throw new UnsupportedOperationException();
  }

  @Override
  public int size() {
    return this.size;
  }

  @Override
  public List<E> subList(int i, int j) {
    return this;
  }

  @Override
  public Object[] toArray() {
    return new Object[] {element};
  }

  @SuppressWarnings("unchecked")
  @Override
  public <T> T[] toArray(T[] arg) {
    Arrays.fill(arg, null);
    arg[0] = (T)element;
    return arg;
  }
}
